package com.punai.system.util;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.punai.common.exception.ServiceException;
import com.punai.common.utils.DictUtils;
import com.punai.system.bo.ep.DepartmentOfWeChat;
import com.punai.system.bo.ep.UserOfDept;
import com.punai.system.bo.ep.UserOfDeptResponse;
import com.punai.system.bo.ep.UserOfWeChat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
public class WeChatComUtil {
    /**
     * 获取access_token URL
     * 请求方式： GET（HTTPS）
     * 请求地址： https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET
     * corpid	是	企业ID，获取方式参考：术语说明-corpid
     * corpsecret	是	应用的凭证密钥，注意应用需要是启用状态，获取方式参考：术语说明-secret
     */
    private static final String getTokenUrl="https://qyapi.weixin.qq.com/cgi-bin/gettoken";

    /**
     * 获取访问用户身份 URL
     * https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token=ACCESS_TOKEN&code=CODE
     */
    private static final String getLoginUserUrl = "https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo";

    /**
     * 获取所有或子部门列表 URL
     请求方式：GET（HTTPS）
     请求地址：https://qyapi.weixin.qq.com/cgi-bin/department/simplelist?access_token=ACCESS_TOKEN&id=ID
     */
    private static final String getDepList="https://qyapi.weixin.qq.com/cgi-bin/department/simplelist";




    /**
     * 获取所有或子部门列表 URL    企业微信API  8月15号之前
     * 请求方式：GET（HTTPS）
     * 请求地址：https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=ACCESS_TOKEN&id=ID
     */
    private static final String getDepListOfOldip = "https://qyapi.weixin.qq.com/cgi-bin/department/list";

    /**
     * 读取成员 URL    企业微信API  8月15号之前
     * 请求方式：GET（HTTPS）
     * 请求地址：https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&userid=USERID
     */
    private static final String getUserInfoOfOldip = "https://qyapi.weixin.qq.com/cgi-bin/user/get";
    /**
     * 获取所有用户列表 URL
     * 请求方式：GET（HTTPS）
     * 请求地址：https://qyapi.weixin.qq.com/cgi-bin/user/list_id?access_token=
     */
    private static final String getUserList = "https://qyapi.weixin.qq.com/cgi-bin/user/list_id";


    /**
     * 获取部门成员详情
     * access_token
     * fetch_child
     * department_id
     */
    private static final String getUserDetailListOfDeptId = "https://qyapi.weixin.qq.com/cgi-bin/user/list";

    /**
     * 平台应用token
     */
    private static String platformToken="";
    private static Long platformTokenEndDate = 0L;
    /**
     * 通讯录Apitoken
     */
    private static String mailListToken = "";
    private static Long mailListTokenEndDate = 0L;

    private static final String dictType = "sys_ep_wx";
    // 企业id
    private static final String qy_id = "qy_id";
    // 通讯录秘钥
    private static final String txl_secret = "txl_secret";
    // 应用id
    private static final String application_id = "application_id";
    // 应用秘钥
    private static final String application_secret = "application_secret";
    // 是否在  时间前创建   在此之前 可调用获取全部部门的API
    private static final String create_201881510_before = "create_201881510_before";
    private static final Logger LOG = LoggerFactory.getLogger(WeChatComUtil.class);

    /**
     *
     * @param code  通过成员授权获取到的code，最大为512字节。每次成员授权带上的code将不一样，code只能使用一次，5分钟未被使用自动过期。
     */
    public String getLoginUser(String code) throws ServiceException {
        String platformToken = getPlatformToken();
        LOG.warn("platformToken:"+ platformToken);
        String body = HttpRequest.get(getLoginUserUrl + "?access_token=" + WeChatComUtil.platformToken + "&code=" + code).execute().body();
        Map map = JSONUtil.toBean(body, Map.class);
        if (StrUtil.equals("0", Convert.toStr(map.get("errcode")))) {
            return Convert.toStr(map.get("userid"));
        } else {
            throw new ServiceException("平台使用微信登录获取用户身份失败，请联系开发人员！错误码：" + Convert.toStr(map.get("errcode")));
        }
    }

    /**
     * 获取全部部门列表或pid部门及其子部门
     * @param pid
     * @throws ServiceException
     */
    public List<DepartmentOfWeChat> getAllDepartment(String pid) throws ServiceException {
        //getPlatformToken();
        //String url = getDepListOfOldip + "?access_token=" + platformToken;
        getMailListToken();
        String url = getDepListOfOldip + "?access_token=" + mailListToken;
        if(StrUtil.isNotBlank(pid)){
            url+="&id=" + pid;
        }
        String body = HttpRequest.get(url).execute().body();
        Map map = JSONUtil.toBean(body, Map.class);
        LOG.warn("deptAll:"+ map);
        if (StrUtil.equals("0", Convert.toStr(map.get("errcode")))) {
            return JSONUtil.toList(JSONUtil.toJsonStr(map.get("department")), DepartmentOfWeChat.class);
        } else{
            throw new ServiceException("平台获取企业微信所有部门失败，请联系开发人员！错误码：" + Convert.toStr(map.get("errcode")));
        }
    }


    /**
     * 递归获取部门下的用户详细信息
     * @param deptId 企业微信部门id
     * @param isSelectChildUser 1 查询子 0 不查询
     */
    public List<UserOfDept> getUserOfDeptId(String deptId,Integer isSelectChildUser) {
        getMailListToken();
        /**
         *      * access_token
         *      * fetch_child
         *      * department_id
         */
        String url = getUserDetailListOfDeptId + "?access_token=" + mailListToken + "&fetch_child="+isSelectChildUser+"&department_id=" + deptId;
        String body = HttpRequest.get(url).execute().body();
        UserOfDeptResponse bean = JSONUtil.toBean(body, UserOfDeptResponse.class);
        if (StrUtil.equals("0", Convert.toStr(bean.getErrcode()))) {
            List<UserOfDept> userlist = bean.getUserlist();
            return userlist;
        } else {
            String errmsg = bean.getErrmsg();
            LOG.error("获取部门下用户接口调用失败{},原因为{}：",url,errmsg);
        }
        return new ArrayList<>();
    }


    /**
     * 获取全部用户及其部门
     *{
     *             "userid": "LiQiang",
     *             "department": 1
     *         }
     * 参数	说明
     * errcode	返回码
     * errmsg	对返回码的文本描述内容
     * next_cursor	分页游标，下次请求时填写以获取之后分页的记录。如果该字段返回空则表示已没有更多数据
     * dept_user	用户-部门关系列表
     * userid	用户userid，当用户在多个部门下时会有多条记录
     * department	用户所属部门
     * @throws ServiceException
     */
    public List<Map<String, Object>> getAllUser(String next_cursor,List<Map<String, Object>> allUser) throws ServiceException {
        String url = getUserList + "?access_token=" + getMailListToken();
        LOG.warn("正在调用接口："+url);
        String finalNext_cursor = next_cursor;
        HashMap<String, Object> objectHashMap = new HashMap<>();
        if(StrUtil.isNotEmpty(next_cursor)){
            objectHashMap.put("cursor", finalNext_cursor);
        }
        objectHashMap.put("limit", 2000);
        String body = HttpRequest.post(url).body(JSONUtil.toJsonStr(objectHashMap)).execute().body();
        LOG.warn(url+"接口调用成功body.length："+body.length());
        Map map = JSONUtil.toBean(body, Map.class);
        LOG.warn(url+"接口调用成功UserMap："+JSONUtil.toJsonStr(map));
        if (StrUtil.equals("0", Convert.toStr(map.get("errcode")))) {
            List<Map> department_id = JSONUtil.toList(JSONUtil.toJsonStr(map.get("dept_user")), Map.class);
            department_id.forEach(v -> {
                String userid = Convert.toStr(v.get("userid"));
                String department = Convert.toStr(v.get("department"));
                List<Map<String, Object>> collect = allUser.stream().filter(l -> StrUtil.equals(Convert.toStr(l.get("userid")), userid)).collect(Collectors.toList());
                if(collect.size()>0){
                    Map<String, Object> objectMap = collect.get(0);
                    int index = allUser.indexOf(objectMap);
                    objectMap.put("department", Convert.toStr(objectMap.get("department")) + "," + department);
                    allUser.add(index,objectMap);
                }else{
                    HashMap<String, Object> hashMap = new HashMap<>();
                    hashMap.put("userid", userid);
                    hashMap.put("department", department);
                    allUser.add(hashMap);
                }
            });
            LOG.warn(url+"接口一次调用处理结束allUser.size："+allUser.size());
            next_cursor = Convert.toStr(map.get("next_cursor"));
            if(StrUtil.isNotEmpty(next_cursor)){
                getAllUser(next_cursor,allUser);
            }
            return allUser;
        } else {
            throw new ServiceException("平台获取企业微信所有用户失败，请联系开发人员！错误码：" + Convert.toStr(map.get("errcode")));
        }
    }

    /**
     * 获取用户信息
     * @throws ServiceException
     */
    public UserOfWeChat getUserInfo(String userId) throws ServiceException {
        // getPlatformToken();
        getMailListToken();
        // String url = getUserInfoOfOldip + "?access_token=" + platformToken + "&userid=" + userId;
        String url = getUserInfoOfOldip + "?access_token=" + mailListToken + "&userid=" + userId;
        String body = HttpRequest.get(url).execute().body();
        UserOfWeChat userOfWeChat = JSONUtil.toBean(body, UserOfWeChat.class);
        if (StrUtil.equals("0", Convert.toStr(userOfWeChat.getErrcode()))) {
            return userOfWeChat;
        } else {
            throw new ServiceException("平台获取企业微信所有用户详情失败，请联系开发人员！错误码：" + Convert.toStr(userOfWeChat.getErrcode()));
        }
    }

    private String getPlatformToken () throws ServiceException {
        if (new Date().getTime() < platformTokenEndDate) return platformToken;
        String body = HttpRequest.get(getTokenUrl +
                "?corpid=" + getCorpid()
                + "&corpsecret=" + getPlatformSecret()).execute().body();
        Map map = JSONUtil.toBean(body, Map.class);
        if(StrUtil.equals("0", Convert.toStr(map.get("errcode")))){
            platformToken = Convert.toStr(map.get("access_token"));
            platformTokenEndDate= new Date().getTime()+(Long.valueOf(Convert.toStr(map.get("expires_in"))) * 1000);
        }else{
            throw new ServiceException("平台使用微信登录获取Token失败，请联系开发人员！错误码：" + Convert.toStr(map.get("errcode")));
        }
        return platformToken;
    }

    private String getMailListToken() throws ServiceException {
        if(new Date().getTime()< mailListTokenEndDate) return mailListToken;
        String body = HttpRequest.get(getTokenUrl +
                "?corpid=" + getCorpid()
                + "&corpsecret=" + getMailListSecret()).execute().body();
        Map map = JSONUtil.toBean(body, Map.class);
        if (StrUtil.equals("0", Convert.toStr(map.get("errcode")))) {
            mailListToken = Convert.toStr(map.get("access_token"));
            mailListTokenEndDate = new Date().getTime() + (Long.valueOf(Convert.toStr(map.get("expires_in")))*1000);
        } else {
            throw new ServiceException("平台获取企业微信通讯录Token失败，请联系开发人员！错误码：" + Convert.toStr(map.get("errcode")));
        }
        return mailListToken;
    }



    public  String getPlatformId() {
        return DictUtils.getDictValue(dictType, application_id);
    }
    public  String getPlatformSecret() {
        return DictUtils.getDictValue(dictType, application_secret);
    }

    public  String getMailListSecret() {
        return DictUtils.getDictValue(dictType, txl_secret);
    }

    public  String getCorpid() {
        return DictUtils.getDictValue(dictType, qy_id);
    }

    public  Boolean getIsOldIp() {
        return "Y".equals(DictUtils.getDictValue(dictType, create_201881510_before));
    }
}



